home *** CD-ROM | disk | FTP | other *** search
/ IRIX Patches 1995 June / SGI IRIX Patches 1995 Jun.iso / 5.3_patches / patchSG0000154 / patchSG0000154.idb / usr / share / src / OpenGL / exts / texobj.c.z / texobj.c
Encoding:
C/C++ Source or Header  |  1995-06-12  |  14.1 KB  |  669 lines

  1. /*
  2. ** texobj.c: Draws textured polygons using the texture object extension.
  3. **
  4. ** Default operation: Draws three squares using a different texture for
  5. ** each square.
  6. **
  7. ** Use -h option to display a list of command line options.  Use Key h 
  8. ** in the created window for key options.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <math.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include "tk.h"
  21.  
  22. #define NUM_LIST_TYPES 3
  23. typedef enum {CUBE=0, SQUARE, PUSHPOP} listType;
  24.  
  25. listType currentList = SQUARE;
  26.  
  27. GLuint lists[NUM_LIST_TYPES];
  28.  
  29. GLenum doubleBuffer, directRender;
  30.  
  31. GLboolean multTex = GL_TRUE;
  32. GLboolean immed = GL_FALSE;
  33. GLboolean texObj = GL_TRUE;
  34. GLboolean queryTexobj = GL_TRUE;
  35.  
  36. #define NUM_TEXTURES 4
  37.  
  38. GLuint texNames[NUM_TEXTURES];
  39. GLfloat texPriorities[NUM_TEXTURES] = {0.1, 0.2, 0.3, 0.4};
  40. TK_RGBImageRec *images[NUM_TEXTURES];
  41. char *texFiles[NUM_TEXTURES] = {
  42.     "../1.rgb",
  43.     "../2.rgb",
  44.     "../3.rgb",
  45.     "../4.rgb",
  46. };
  47.  
  48.  
  49. float *minFilter, *magFilter, *sWrapMode, *tWrapMode;
  50. float decal[] = {GL_DECAL};
  51. float modulate[] = {GL_MODULATE};
  52. float repeat[] = {GL_REPEAT};
  53. float clamp[] = {GL_CLAMP};
  54. float nr[] = {GL_NEAREST};
  55. float ln[] = {GL_LINEAR};
  56. float nr_mipmap_nr[] = {GL_NEAREST_MIPMAP_NEAREST};
  57. float nr_mipmap_ln[] = {GL_NEAREST_MIPMAP_LINEAR};
  58. float ln_mipmap_nr[] = {GL_LINEAR_MIPMAP_NEAREST};
  59. float ln_mipmap_ln[] = {GL_LINEAR_MIPMAP_LINEAR};
  60. GLint sphereMap[] = {GL_SPHERE_MAP};
  61.  
  62. GLenum doSphere = GL_FALSE;
  63. float xRotation = 0.0, yRotation = 0.0, zTranslate = -3.125;
  64.  
  65. float c[6][4][3] = {
  66.     {
  67.     { 1.0, 1.0, -1.0 },
  68.     { -1.0, 1.0, -1.0 },
  69.     { -1.0, -1.0, -1.0 },
  70.     { 1.0, -1.0, -1.0 }
  71.     },
  72.     {
  73.     { 1.0, 1.0, 1.0 },
  74.     { 1.0, 1.0, -1.0 },
  75.     { 1.0, -1.0, -1.0 },
  76.     { 1.0, -1.0, 1.0 }
  77.     },
  78.     {
  79.     { -1.0, 1.0, 1.0 },
  80.     { 1.0, 1.0, 1.0 },
  81.     { 1.0, -1.0, 1.0 },
  82.     { -1.0, -1.0, 1.0 }
  83.     },
  84.     {
  85.     { -1.0, 1.0, -1.0 },
  86.     { -1.0, 1.0, 1.0 },
  87.     { -1.0, -1.0, 1.0 },
  88.     { -1.0, -1.0, -1.0 }
  89.     },
  90.     {
  91.     { -1.0, 1.0, 1.0 },
  92.     { -1.0, 1.0, -1.0 },
  93.     { 1.0, 1.0, -1.0 },
  94.     { 1.0, 1.0, 1.0 }
  95.     },
  96.     {
  97.     { -1.0, -1.0, -1.0 },
  98.     { -1.0, -1.0, 1.0 },
  99.     { 1.0, -1.0, 1.0 },
  100.     { 1.0, -1.0, -1.0 }
  101.     }
  102. };
  103. static float n[6][3] = {
  104.     { 0.0, 0.0, -1.0 },
  105.     { 1.0, 0.0, 0.0 },
  106.     { 0.0, 0.0, 1.0 },
  107.     { -1.0, 0.0, 0.0 },
  108.     { 0.0, 1.0, 0.0 },
  109.     { 0.0, -1.0, 0.0 }
  110. };
  111. static float t[6][4][2] = {
  112.     {
  113.     { 1.1,  1.1 },
  114.     { -0.1, 1.1 },
  115.     { -0.1, -0.1 },
  116.     { 1.1,  -0.1 }
  117.     },
  118.     {
  119.     { 1.1,  1.1 },
  120.     { -0.1, 1.1 },
  121.     { -0.1, -0.1 },
  122.     { 1.1,  -0.1 }
  123.     },
  124.     {
  125.     { -0.1,  1.1 },
  126.     { 1.1, 1.1 },
  127.     { 1.1, -0.1 },
  128.     { -0.1,  -0.1 }
  129.     },
  130.     {
  131.     { 1.1,  1.1 },
  132.     { -0.1, 1.1 },
  133.     { -0.1, -0.1 },
  134.     { 1.1,  -0.1 }
  135.     },
  136.     {
  137.     { 1.1,  1.1 },
  138.     { -0.1, 1.1 },
  139.     { -0.1, -0.1 },
  140.     { 1.1,  -0.1 }
  141.     },
  142.     {
  143.     { 1.1,  1.1 },
  144.     { -0.1, 1.1 },
  145.     { -0.1, -0.1 },
  146.     { 1.1,  -0.1 }
  147.     },
  148. };
  149.  
  150.  
  151. static void SelectTexture(GLint i)
  152. {
  153.     TK_RGBImageRec *texImage;
  154.  
  155.     if (texObj) {
  156.     if (i<NUM_TEXTURES)
  157.         glBindTextureEXT(GL_TEXTURE_2D, texNames[i]);
  158.     else
  159.         glBindTextureEXT(GL_TEXTURE_2D, 0);
  160.     return;
  161.     }
  162.  
  163.     if (i >= NUM_TEXTURES) i = NUM_TEXTURES-1;
  164.  
  165.     texImage = images[i];
  166.  
  167.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texImage->sizeX, texImage->sizeY,
  168.               GL_RGB, GL_UNSIGNED_BYTE, texImage->data);
  169. }
  170.  
  171. static void DrawCube(void)
  172. {
  173.     GLint i;
  174.  
  175.     for (i = 0; i < 6; i++) {
  176.     if (multTex) SelectTexture(i);
  177.     glBegin(GL_POLYGON);
  178.         glNormal3fv(n[i]); glTexCoord2fv(t[i][0]); glVertex3fv(c[i][0]);
  179.         glNormal3fv(n[i]); glTexCoord2fv(t[i][1]); glVertex3fv(c[i][1]);
  180.         glNormal3fv(n[i]); glTexCoord2fv(t[i][2]); glVertex3fv(c[i][2]);
  181.         glNormal3fv(n[i]); glTexCoord2fv(t[i][3]); glVertex3fv(c[i][3]);
  182.     glEnd();
  183.     }
  184. }
  185.  
  186. static void BuildCube(void)
  187. {
  188.     GLint i;
  189.  
  190.     glNewList(lists[CUBE], GL_COMPILE);
  191.     DrawCube();
  192.     glEndList();
  193. }
  194.  
  195. static void DrawSquare(void)
  196. {
  197.     glBegin(GL_POLYGON);
  198.     glNormal3fv(n[2]); glTexCoord2fv(t[2][0]); glVertex3fv(c[2][0]);
  199.     glNormal3fv(n[2]); glTexCoord2fv(t[2][1]); glVertex3fv(c[2][1]);
  200.     glNormal3fv(n[2]); glTexCoord2fv(t[2][2]); glVertex3fv(c[2][2]);
  201.     glNormal3fv(n[2]); glTexCoord2fv(t[2][3]); glVertex3fv(c[2][3]);
  202.     glEnd();
  203. }
  204.  
  205. static void DrawSquares(void)
  206. {
  207.     GLint i;
  208.     GLfloat xTranslate = 0.0;
  209.  
  210.     glTranslatef(-2.0, 0.0, 0.0);
  211.     for (i = 0; i < 3; i++) {
  212.     if (multTex) SelectTexture(i);
  213.     DrawSquare();
  214.     glTranslatef(2.0, 0.0, 0.0);
  215.     }
  216. }
  217.  
  218. static void BuildSquare(void)
  219. {
  220.     GLint i;
  221.     GLfloat xTranslate = 0.0;
  222.  
  223.     glNewList(lists[SQUARE], GL_COMPILE);
  224.     DrawSquares();
  225.     glEndList();
  226. }
  227.  
  228. static void DoPushPopTest(void)
  229. {
  230.     GLfloat xTranslate = 0.0;
  231.  
  232.     if (multTex) SelectTexture(1);
  233.     glTranslatef(-4.0, 0.0, 0.0);
  234.     DrawSquare();
  235.  
  236.     glPushAttrib(GL_TEXTURE_BIT);
  237.     if (multTex) SelectTexture(2);
  238.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
  239.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
  240.     glTranslatef(2.0, 0.0, 0.0);
  241.     DrawSquare();
  242.  
  243.     glPopAttrib();
  244.     glTranslatef(2.0, 0.0, 0.0);
  245.     DrawSquare();
  246.  
  247.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
  248.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
  249.     glTranslatef(2.0, 0.0, 0.0);
  250.     DrawSquare();
  251.  
  252. }
  253.  
  254. static void BuildPushPopTest(void)
  255. {
  256.     GLfloat xTranslate = 0.0;
  257.  
  258.     glNewList(lists[PUSHPOP], GL_COMPILE);
  259.     DoPushPopTest();
  260.     glEndList();
  261. }
  262.  
  263. static void BuildLists(void)
  264. {
  265.  
  266.     lists[CUBE] = glGenLists(1);
  267.     BuildCube();
  268.     lists[SQUARE] = glGenLists(1);
  269.     BuildSquare();
  270.     lists[PUSHPOP] = glGenLists(1);
  271.     BuildPushPopTest();
  272. }
  273. static void UnBuildLists(void)
  274. {
  275.     int i;
  276.     for (i=0; i<NUM_LIST_TYPES; i++) {
  277.     glDeleteLists(lists[i], 1);
  278.     }
  279. }
  280.  
  281. static void Init(void)
  282. {
  283.  
  284.     doSphere = GL_FALSE;
  285.     xRotation = 0.0;
  286.     yRotation = 0.0;
  287.     zTranslate = -3.125;
  288.  
  289.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  290.  
  291.     if (multTex && texObj) {
  292.     int i;
  293.  
  294.     glGenTexturesEXT(NUM_TEXTURES, texNames);
  295.     for (i=1; i < NUM_TEXTURES; i++) {
  296.         glBindTextureEXT(GL_TEXTURE_2D, texNames[i]);
  297.         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 
  298.             images[i]->sizeX, images[i]->sizeY,
  299.             GL_RGB, GL_UNSIGNED_BYTE, images[i]->data);
  300.     }
  301.     glBindTextureEXT(GL_TEXTURE_2D, texNames[0]);
  302.     glPrioritizeTexturesEXT(NUM_TEXTURES, texNames, texPriorities);
  303.     }
  304.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, images[0]->sizeX, images[0]->sizeY,
  305.               GL_RGB, GL_UNSIGNED_BYTE, images[0]->data);
  306.  
  307.     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, decal);
  308.     glEnable(GL_TEXTURE_2D);
  309.  
  310.     glFrontFace(GL_CCW);
  311.     glCullFace(GL_FRONT);
  312.     glEnable(GL_CULL_FACE);
  313.  
  314.     BuildLists();
  315.  
  316.     glClearColor(0.0, 0.0, 0.0, 0.0);
  317.  
  318.     magFilter = nr;
  319.     minFilter = nr;
  320.     sWrapMode = repeat;
  321.     tWrapMode = repeat;
  322. }
  323.  
  324. static void UnInit(void)
  325. {
  326.  
  327.     if (multTex && texObj) {
  328.     glDeleteTexturesEXT(NUM_TEXTURES, texNames);
  329.     }
  330.  
  331.     UnBuildLists();
  332. }
  333.  
  334. static void Reshape(int width, int height)
  335. {
  336.  
  337.     glViewport(0, 0, (GLint)width, (GLint)height);
  338.  
  339.     glMatrixMode(GL_PROJECTION);
  340.     glLoadIdentity();
  341.     gluPerspective(145.0, 1.0, 0.01, 1000);
  342.     glMatrixMode(GL_MODELVIEW);
  343. }
  344.  
  345. static char *keyList[][2] = {
  346.     {"left arrow", "y rotation - 0.5"},
  347.     {"right arrow", "y rotation + 0.5"},
  348.     {"up arrow", "x rotation - 0.5"},
  349.     {"down arrow", "x rotation + 0.5"},
  350.     {"T", "z translate  + 0.25"},
  351.     {"t", "z translate  - 0.25"},
  352.     {"",""},
  353.     {"s", "toggle texgen sphereMap"},
  354.     {"R", "Reset draw routine"},
  355.     {"C", "Draw Cube"},
  356.     {"S", "Draw Squares"},
  357.     {"P", "Push Pop test"},
  358.     {"G", "Get attrib test"},
  359.     {"",""},
  360.     {"0", "magfilter = nearest"},
  361.     {"1", "magfilter = linear"},
  362.     {"2", "minfilter = nearest"},
  363.     {"3", "minfilter = linear"},
  364.     {"4", "minfilter = nearest mipmap nearest"},
  365.     {"5", "minfilter = nearest mipmap linear"},
  366.     {"6", "minfilter = linear mipmap nearest"},
  367.     {"7", "minfilter = linear mipmap linear"},
  368.     {"",""},
  369.     {"h", "print this list"},
  370.     {"ESC", "exit"},
  371.     {NULL, NULL}
  372. };
  373.  
  374. static GLenum Key(int key, GLenum mask)
  375. {
  376.  
  377.     switch (key) {
  378.       case TK_ESCAPE:
  379.     tkQuit();
  380.       
  381.       case TK_h:
  382.     {
  383.       int i;
  384.       for (i=0; keyList[i][0] != NULL; i++) {
  385.         printf("%-20s %s\n", keyList[i][0], keyList[i][1]);
  386.       }
  387.     }
  388.     break;
  389.  
  390.       case TK_LEFT:
  391.     yRotation -= 0.5;
  392.     break;
  393.       case TK_RIGHT:
  394.     yRotation += 0.5;
  395.     break;
  396.       case TK_UP:
  397.     xRotation -= 0.5;
  398.     break;
  399.       case TK_DOWN:
  400.     xRotation += 0.5;
  401.     break;
  402.       case TK_T:
  403.     zTranslate += 0.25;
  404.     break;
  405.       case TK_t:
  406.     zTranslate -= 0.25;
  407.     break;
  408.  
  409.       case TK_s:
  410.     doSphere = !doSphere;
  411.     if (doSphere) {
  412.         glTexGeniv(GL_S, GL_TEXTURE_GEN_MODE, sphereMap);
  413.         glTexGeniv(GL_T, GL_TEXTURE_GEN_MODE, sphereMap);
  414.         glEnable(GL_TEXTURE_GEN_S);
  415.         glEnable(GL_TEXTURE_GEN_T);
  416.     } else {
  417.         glDisable(GL_TEXTURE_GEN_S);
  418.         glDisable(GL_TEXTURE_GEN_T);
  419.     }
  420.     break;
  421.  
  422.       case TK_R:     /* restart */
  423.     UnInit();
  424.     Init();
  425.     break;
  426.  
  427.       case TK_C:    /* draw cube */
  428.     currentList = CUBE;
  429.     break;
  430.       case TK_S:    /* draw squares */
  431.     currentList = SQUARE;
  432.     break;
  433.       case TK_P:    /* do push pop test */
  434.     currentList = PUSHPOP;
  435.     break;
  436.  
  437.       case TK_G:     /* do Get test */
  438.     {
  439.         GLint name;
  440.         GLfloat priority;
  441.         GLboolean isTex, resident, residences[NUM_TEXTURES];
  442.  
  443.         glGetIntegerv(GL_TEXTURE_2D_BINDING_EXT, &name);
  444.         glGetTexParameterfv(GL_TEXTURE_2D, 
  445.                 GL_TEXTURE_PRIORITY_EXT, &priority);
  446.         isTex = glIsTextureEXT(name);
  447.         resident = glAreTexturesResidentEXT(NUM_TEXTURES, 
  448.                         texNames, residences);
  449.         fprintf(stdout, 
  450.           "\tname=%d priority=%f allResident=%d isTex=%d\n", 
  451.           name, priority, resident, isTex);
  452.     }
  453.         break;
  454.     
  455.       case TK_0:
  456.     magFilter = nr;
  457.     break;
  458.       case TK_1:
  459.     magFilter = ln;
  460.     break;
  461.       case TK_2:
  462.     minFilter = nr;
  463.     break;
  464.       case TK_3:
  465.     minFilter = ln;
  466.     break;
  467.       case TK_4:
  468.     minFilter = nr_mipmap_nr;
  469.     break;
  470.       case TK_5:
  471.     minFilter = nr_mipmap_ln;
  472.     break;
  473.       case TK_6:
  474.     minFilter = ln_mipmap_nr;
  475.     break;
  476.       case TK_7:
  477.     minFilter = ln_mipmap_ln;
  478.     break;
  479.  
  480.       default:
  481.     return GL_FALSE;
  482.     }
  483.     return GL_TRUE;
  484. }
  485.  
  486. static void Draw(void)
  487. {
  488.     glClear(GL_COLOR_BUFFER_BIT);
  489.  
  490.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sWrapMode);
  491.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tWrapMode);
  492.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
  493.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
  494.  
  495.     glPushMatrix();
  496.  
  497.     glTranslatef(0.0, 0.0, zTranslate);
  498.     glRotatef(xRotation, 1, 0, 0);
  499.     glRotatef(yRotation, 0, 1, 0);
  500.  
  501.     if (immed) {         
  502.     switch(currentList) {
  503.     case SQUARE:
  504.         DrawSquares();
  505.         break;
  506.     case PUSHPOP:
  507.         DoPushPopTest();
  508.         break;
  509.     case CUBE:
  510.         DrawCube();
  511.         break;
  512.     }
  513.     }
  514.     else {
  515.     glCallList(lists[currentList]);
  516.     }
  517.  
  518.     glPopMatrix();
  519.  
  520.     glFlush();
  521.  
  522.     if (doubleBuffer) {
  523.     tkSwapBuffers();
  524.     }
  525. }
  526.  
  527. static char *argList[][2] = {
  528.     {"-sb", "single buffered"},
  529.     {"-db", "double buffered"},
  530.     {"-dr", "direct rendering"},
  531.     {"-ir", "indirect rendering"},
  532.     {"-f filename", "filename for texture"},
  533.     {"-texobj", "use texture objects"},
  534.     {"-notexobj", "don't use texture objects"},
  535.     {"-immed", "immediate mode"},
  536.     {"-square", "draw squares"},
  537.     {"-cube", "draw cube"},
  538.     {"-pushpop", "push pop test"},
  539.     {"-nq", "skip query texobj extension"},
  540.     {"-h", "display this list"},
  541.     {"Press H in app window to get key interpretations", ""},
  542.     {NULL, NULL}
  543. };
  544.  
  545. static GLenum Args(int argc, char **argv)
  546. {
  547.     GLint i;
  548.  
  549.     doubleBuffer = GL_FALSE;
  550.     directRender = GL_TRUE;
  551.  
  552.     for (i = 1; i < argc; i++) {
  553.     if (strcmp(argv[i], "-sb") == 0) {
  554.         doubleBuffer = GL_FALSE;
  555.     } else if (strcmp(argv[i], "-db") == 0) {
  556.         doubleBuffer = GL_TRUE;
  557.     } else if (strcmp(argv[i], "-dr") == 0) {
  558.         directRender = GL_TRUE;
  559.     } else if (strcmp(argv[i], "-ir") == 0) {
  560.         directRender = GL_FALSE;
  561.     } else if (strcmp(argv[i], "-f") == 0) {
  562.         if (i+1 >= argc || argv[i+1][0] == '-') {
  563.         printf("-f (No file name).\n");
  564.         return GL_FALSE;
  565.         } else {
  566.         texFiles[0] = argv[++i];
  567.         multTex = GL_FALSE;
  568.         }
  569.     } else if (strcmp(argv[i], "-flat") == 0) {
  570.         currentList = SQUARE;
  571.     } else if (strcmp(argv[i], "-texobj") == 0) {
  572.         texObj = GL_TRUE;
  573.     } else if (strcmp(argv[i], "-notexobj") == 0) {
  574.         texObj = GL_FALSE;
  575.     } else if (strcmp(argv[i], "-immed") == 0) {
  576.         immed = GL_TRUE;
  577.     } else if (strcmp(argv[i], "-pushpop") == 0) {
  578.         currentList = PUSHPOP;
  579.     } else if (strcmp(argv[i], "-cube") == 0) {
  580.         currentList = CUBE;
  581.     } else if (strcmp(argv[i], "-nq") == 0) {
  582.         queryTexobj = GL_FALSE;
  583.     } else if (strcmp(argv[i], "-h") == 0) {
  584.         int i;
  585.         for (i=0; argList[i][0] != NULL; i++) {
  586.         printf("%-30s %s\n", argList[i][0], argList[i][1]);
  587.         }
  588.         exit(0);
  589.     } else {
  590.         printf("%s (Bad option).\n", argv[i]);
  591.         return GL_FALSE;
  592.     }
  593.     }
  594.     return GL_TRUE;
  595. }
  596.  
  597. static GLboolean queryExtension(char *extName)
  598. {
  599.     /*
  600.     ** Search for extName in the extensions string.  Use of strstr()
  601.     ** is not sufficient because extension names can be prefixes of
  602.     ** other extension names.  Could use strtok() but the constant
  603.     ** string returned by glGetString can be in read-only memory.
  604.     */
  605.     char *p;
  606.     char *end;
  607.     int extNameLen;
  608.  
  609.     if (!queryTexobj) return GL_TRUE;
  610.  
  611.     extNameLen = strlen(extName);
  612.  
  613.     p = (char *) glGetString(GL_EXTENSIONS);
  614.     if (NULL == p) return GL_FALSE;
  615.  
  616.     end = p + strlen(p);
  617.  
  618.     while (p < end) {
  619.     int n = strcspn(p, " ");
  620.     if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
  621.         return GL_TRUE;
  622.     }
  623.     p += (n + 1);
  624.     }
  625.     return GL_FALSE;
  626. }
  627.  
  628. void main(int argc, char **argv)
  629. {
  630.     GLenum type;
  631.  
  632.     if (Args(argc, argv) == GL_FALSE) {
  633.     tkQuit();
  634.     }
  635.  
  636.     tkInitPosition(0, 0, 300, 300);
  637.  
  638.     type = TK_RGB;
  639.     type |= (doubleBuffer) ? TK_DOUBLE : TK_SINGLE;
  640.     type |= (directRender) ? TK_DIRECT : TK_INDIRECT;
  641.     tkInitDisplayMode(type);
  642.  
  643.     if (tkInitWindow("Texture Test") == GL_FALSE) {
  644.     tkQuit();
  645.     }
  646.  
  647.     if (texObj && !queryExtension("GL_EXT_texture_object")) {
  648.     fprintf(stdout, "Warning: texture object extension not found.\n");
  649.     fprintf(stdout, "         Disabling texture objects.\n");
  650.     texObj = GL_FALSE;
  651.     }
  652.  
  653.     images[0] = tkRGBImageLoad(texFiles[0]);
  654.     if (multTex) {
  655.     int i;
  656.     for (i=1; i < NUM_TEXTURES; i++) {
  657.         images[i] = tkRGBImageLoad(texFiles[i]);
  658.     }
  659.     }
  660.  
  661.     Init();
  662.  
  663.     tkExposeFunc(Reshape);
  664.     tkReshapeFunc(Reshape);
  665.     tkKeyDownFunc(Key);
  666.     tkDisplayFunc(Draw);
  667.     tkExec();
  668. }
  669.